//implement multi-thread mechanism classes interfaces
//use windows api

#include "NameSpaceDef.h"
#include ADD_QUOTE(INC_NAME_HEADER(NAMESPACE_NAME, Thread.h))

BEGIN_CXX_NAMESPACE_DEFINITION

//----------------------------implement Mutex----------------------------

Mutex::Mutex()
{
	InitializeCriticalSectionAndSpinCount(&m_mutex, 4000);
}

Mutex::~Mutex()
{
	DeleteCriticalSection(&m_mutex);
}

void Mutex::lock()
{
	EnterCriticalSection(&m_mutex);
}

void Mutex::unlock()
{
	LeaveCriticalSection(&m_mutex);
}

//----------------------------implement Event------------------------------

Event::Event()
{
	m_event = CreateEvent(NULL, FALSE, FALSE, NULL);
}

Event::~Event()
{
	CloseHandle(m_event);
}

void Event::set()
{
	SetEvent(m_event);
}

void Event::wait()
{
	WaitForSingleObject(m_event, INFINITE);
}

Event::WAITRE Event::wait(long msecs)
{
	if (WaitForSingleObject(m_event, msecs) == WAIT_TIMEOUT)
		return TIMEOUT;
	return OK;
}

//----------------------------implement Thread-------------------------------

Thread::Thread() : m_tid(0), m_threadH(0), m_isThreadBegin(false)
{
}

Thread::~Thread()
{
	if (m_threadH)
		CloseHandle(m_threadH);
}

void Thread::start()
{
	m_threadH = CreateThread(NULL, 0, thread_fun, this, 0, &m_tid);
}

void Thread::join()
{
	if (!m_threadH)
		return;
	WaitForSingleObject(m_threadH, INFINITE);
	CloseHandle(m_threadH);
	m_threadH = 0;
}

void Thread::sleep(long secs)
{
	Sleep(DWORD(secs * 1000));
}

void Thread::msleep(long msecs)
{
	Sleep(DWORD(msecs));
}

void Thread::usleep(long usecs)
{
	static Mutex _mutex;
	_mutex.lock();
	static bool isInit = false;
	static LARGE_INTEGER freq;
	static LONGLONG usFreq;
	if (!isInit)
	{
		QueryPerformanceFrequency(&freq);
		usFreq = freq.QuadPart / 1000000LL;
		isInit = true;
	}
	_mutex.unlock();
	LARGE_INTEGER begin, end;
	QueryPerformanceCounter(&begin);
	do 
	{
		QueryPerformanceCounter(&end);
		if (end.QuadPart - begin.QuadPart > usFreq * usecs)
			break;
		Sleep(0);
	} while (true);
}

DWORD WINAPI Thread::thread_fun(LPVOID lpParam)
{
	Thread* thr = reinterpret_cast<Thread*>(lpParam);
	thr->m_isThreadBegin = true;
	thr->run();
	thr->m_isThreadBegin = false;
	return 0;
}

END_CXX_NAMESPACE_DEFINITION